package com.bball.court.controller.play;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

import android.location.Location;
import android.test.InstrumentationTestCase;

import com.bball.court.http.DeleteCourtRequestCallbacks;
import com.bball.court.http.GetCourtsRequestCallbacks;
import com.bball.court.model.Court;
import com.bball.court.model.CourtList;
import com.bball.court.model.play.PlayCourt;
import com.bball.court.util.DistanceUtil;

public class PlayCourtControllerTest extends InstrumentationTestCase {

    private PlayCourtController courtController;
    private PlayCourt court;
    private double latitude = 45.499384;
    private double longitude = -73.56028;
    private CountDownLatch signal;
    private Location location;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        location = new Location("Test");
        location.setLatitude(latitude);
        location.setLongitude(longitude);
        courtController = new PlayCourtController(getInstrumentation().getTargetContext());
        court = new PlayCourt("Tour de la bourse", 45.50037642476354, -73.56118619441986, "530 Rue Gauvin", "Montréal", "Canada");
    }

    public void testGetCourtInfoPart() throws IOException {
        String courtInfosPart = courtController.getCourtInfosPart(court);
        assertEquals(
                "--*****\r\n"
                        + "Content-Disposition: form-data; name=\"json\"\r\n"
                        + "Content-Type: application/json;charset=UTF-8\r\n"
                        + "Content-Length: 233\r\n\r\n"
                        + "%7B%22address%22%3A%22530%20Rue%20Gauvin%22%2C%22city%22%3A%22Montr%C3%A9al%22%2C%22country%22%3A%22Canada%22%2C%22latitude%22%3A45.50037642476354%2C%22longitude%22%3A-73.56118619441986%2C%22name%22%3A%22Tour%20de%20la%20bourse%22%7D\r\n"
                        + "--*****\r\n" + "Content-Disposition: form-data; name=\"images\";filename=\"court.png\"\r\nContent-Type: image/png\r\n\r\n",
                courtInfosPart);

    }

    public void testGetClosestCourt() throws InterruptedException {
        signal = new CountDownLatch(1);
        courtController.findClosestCourt(new MockCourtsRequestCallbacks(10000), latitude, longitude);
        signal.await();
    }

    public void testGetCourtAttributes() throws InterruptedException {
        signal = new CountDownLatch(1);
        courtController.findClosestCourt(new GetCourtsRequestCallbacks() {

            @Override
            public void onGetCourtsRequestFailed(RuntimeException runtimeException) {
                fail();
            }

            @Override
            public void onGetCourtsRequestComplete(CourtList courts) {
                assertEquals(2, courts.size());
                Court court = courts.get(0);
                assertEquals("186.43 m", DistanceUtil.formatDistance(court.getDistance(location)));
                assertEquals(45.500970492964285, court.getLatLng()[0]);
                assertEquals(-73.55952322483063, court.getLatLng()[1]);
                signal.countDown();
            }
        }, latitude, longitude, 2);
        signal.await();
    }

    public void testGetClosestCourtByDistance() throws InterruptedException {
        signal = new CountDownLatch(8);
        courtController.findClosestCourt(new MockCourtsRequestCallbacks(1), latitude, longitude, 1);
        courtController.findClosestCourt(new MockCourtsRequestCallbacks(2), latitude, longitude, 2);
        courtController.findClosestCourt(new MockCourtsRequestCallbacks(3), latitude, longitude, 3);
        courtController.findClosestCourt(new MockCourtsRequestCallbacks(4), latitude, longitude, 4);
        courtController.findClosestCourt(new MockCourtsRequestCallbacks(5), latitude, longitude, 5);
        courtController.findClosestCourt(new MockCourtsRequestCallbacks(6), latitude, longitude, 6);
        courtController.findClosestCourt(new MockCourtsRequestCallbacks(7), latitude, longitude, 7);
        courtController.findClosestCourt(new MockCourtsRequestCallbacks(8), latitude, longitude, 8);
        signal.await();
    }

    private class MockCourtsRequestCallbacks implements GetCourtsRequestCallbacks {

        private int distance;

        public MockCourtsRequestCallbacks(int distance) {
            this.distance = distance;
        }

        @Override
        public void onGetCourtsRequestComplete(CourtList courts) {
            int result = getResultAttended(distance);
            assertEquals(result, courts.size());
            signal.countDown();
        }

        private int getResultAttended(int distance) {
            switch (distance) {
            case 1:
                return 1;
            case 2:
                return 2;
            case 3:
            case 4:
                return 3;
            case 5:
                return 5;
            case 6:
                return 6;
            case 7:
                return 9;
            default:
                return 10;
            }
        }

        @Override
        public void onGetCourtsRequestFailed(RuntimeException runtimeException) {
            fail();
        }
    }
    
    /*
     * public void testAddSuggectedCourt() throws IOException { InputStream inputStream =
     * getInstrumentation().getTargetContext().getResources().openRawResource(R.raw.player_logo);
     * courtController.addSuggestedCourt(court, inputStream); }
     * 
     * public void testDeleteCourt() throws IOException, InterruptedException { signal = new CountDownLatch(1);
     * courtController.deleteCourt("bd85ce5e-6597-4347-8d57-e57a06f021c0", new
     * MockCourtDeleteCallbacks("bd85ce5e-6597-4347-8d57-e57a06f021c0")); signal.await(); }
     */

    private class MockCourtDeleteCallbacks implements DeleteCourtRequestCallbacks {

        private String courtId;

        public MockCourtDeleteCallbacks(String courtId) {
            this.courtId = courtId;
        }

        @Override
        public void onDeleteCourtsComplete(String courtId) {
            assertEquals(this.courtId, courtId);
        }

        @Override
        public void onDeleteCourtsFailed(RuntimeException runtimeException) {
            fail();
        }
    }

}
